package com.jy.admin.jobs;

import com.alibaba.fastjson.JSON;
import com.fqgj.common.api.Page;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.HttpUtil;
import com.fqgj.common.utils.StringUtils;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.jsoniter.JsonIterator;
import com.jsoniter.any.Any;
import com.jsoniter.output.JsonStream;
import com.jy.admin.config.ApolloConfigUtil;
import com.jy.admin.db.dao.*;
import com.jy.admin.db.entity.*;
import com.jy.admin.enums.SendTaskStatusEnum;
import com.jy.admin.enums.SmsLogStatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 * User: sm
 * Date: 2021/11/28
 * Time: 10:28 下午
 */
@Service
public class SendSmsJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(SendSmsJob.class);

    private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat("send-sms-pool-%d").build();

    private static ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10240), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


    @Autowired
    private OpdCsvExpandDao opdCsvExpandDao;

    @Autowired
    private SmsSendTaskDao smsSendTaskDao;

    @Autowired
    private SmsSendChannelDao smsSendChannelDao;

    @Autowired
    private SmsTemplateDao smsTemplateDao;

    @Autowired
    private SmsSendLogDao smsSendLogDao;

    @Autowired
    private ApolloConfigUtil configUtil;


//    @Scheduled(fixedDelay = 1000L * 20)
    public void run() {

        LOGGER.info("== sms-send start sending sms ==");

        if (!configUtil.getSendSmsSwitch()) {

            LOGGER.info("== sms-send start sending sms, switch not open ==");
            return;
        }

        List<SmsSendTaskEntity> watingList = smsSendTaskDao.getListByStatus(SendTaskStatusEnum.create_pre_success.getStatus());
        if (CollectionUtils.isEmpty(watingList)) {
            LOGGER.info("==sms-send  start sending sms  ==,size=0");
            return;
        }

        LOGGER.info("==sms-send  start sending sms ==,size:{}", watingList.size());

        watingList.forEach(smsSendTaskEntity -> {

            smsSendTaskEntity.setStatus(SendTaskStatusEnum.Doing.getStatus());
            smsSendTaskDao.updateByPrimaryKey(smsSendTaskEntity);

            SmsSendChannelEntity channelEntity = smsSendChannelDao.getByChannelCode(smsSendTaskEntity.getChannleCode());
            SmsTemplateEntity template = smsTemplateDao.getByTemplateNo(smsSendTaskEntity.getTemplateNo());
            if (channelEntity == null) {
                smsSendTaskEntity.setStatus(SendTaskStatusEnum.Exception.getStatus());
                smsSendTaskDao.updateByPrimaryKey(smsSendTaskEntity);
                LOGGER.error("==sms-send  start sending sms ==,channelEntity || templateEntity is null,taskNo:{}", smsSendTaskEntity.getTaskNo());
                return;
            }

            LOGGER.info("==sms-send  start sending sms ==,taskNo:{}", smsSendTaskEntity.getTaskNo());


            int pageSize = 1000;
            int currentPage = 1;
            Page page1 = new Page();
            page1.setCurrentPage(currentPage);
            page1.setPageSize(pageSize);

            while (true) {
                List<SmsSendLogEntity> smsSendLogEntities = smsSendLogDao.selectListByStatusAndPage(smsSendTaskEntity.getTaskNo(), SmsLogStatusEnum.waiting.getStatus(), page1);
                if (CollectionUtils.isEmpty(smsSendLogEntities)) {
                    LOGGER.info("===sms-send  listByDataNo size ==0 ==");
                    smsSendTaskEntity.setStatus(SendTaskStatusEnum.Success.getStatus());
                    smsSendTaskDao.updateByPrimaryKey(smsSendTaskEntity);
                    return;
                }
                LOGGER.info("===sms-send  listByDataNo size:{} ==", smsSendLogEntities.size());

                if (pool.getQueue().remainingCapacity() < smsSendLogEntities.size()) {
                    LOGGER.info("== 线程池队列数量小于要新加的数据长度 休眠5s ==");
                    try {
                        Thread.sleep(5000L);
                    } catch (InterruptedException e) {
                        LOGGER.error("== 线程池队列数量小于要新加的数据长度 error ===", e);
                    }

                    continue;
                }


                List<Long> ids = new ArrayList<>();
                smsSendLogEntities.forEach(smsSendLogEntity -> {
                    if (StringUtils.isEmpty(smsSendLogEntity.getMobile())) {
                        return;
                    }
                    LOGGER.info("===sms-send  mobile detail  ==,taskNo:{},mobile:{}", smsSendLogEntity.getTaskNo(), smsSendLogEntity.getMobile());
                    sendMsg(channelEntity, smsSendLogEntity, template.getSender());
                    ids.add(smsSendLogEntity.getId());
                });

                if (CollectionUtils.isEmpty(ids)) {
                    continue;
                }

                smsSendLogDao.updateBatchSendResult(ids, SmsLogStatusEnum.send_success.getStatus(), "success");

                if (smsSendLogEntities.size() < pageSize) {
                    smsSendTaskEntity.setStatus(SendTaskStatusEnum.Success.getStatus());
                    smsSendTaskDao.updateByPrimaryKey(smsSendTaskEntity);
                    break;
                }

                currentPage++;
                page1.setCurrentPage(currentPage);
            }
        });
    }


    private SendSmsRes sendMsg(SmsSendChannelEntity channel, SmsSendLogEntity smsSendLog, String sender) {
        if (configUtil.getSmsSendMock()) {
            return new SendSmsRes("0", "mocked");
        }


        String provider = channel.getProvider();
        if ("nx".equalsIgnoreCase(provider)) {
            return sendByNx(channel, smsSendLog.getMobile(), smsSendLog.getContent(), sender);
        } else if ("ps".equalsIgnoreCase(provider)) {
            return sendByPasso(channel, smsSendLog.getMobile(), smsSendLog.getContent(), sender);
        } else {
            LOGGER.info("== sms-send no sender match ==");
            return new SendSmsRes("400", "no sender found");
        }
    }


    private SendSmsRes sendByNx(SmsSendChannelEntity channel, String mobile, String content, String sender) {

        pool.submit(new Runnable() {
            @Override
            public void run() {
                MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
                body.add("appkey", channel.getAccessKey());
                body.add("secretkey", channel.getAccessSecret());
                body.add("phone", "91" + mobile);
                body.add("content", content);
                body.add("source_address", sender);
                LOGGER.info("== nx-batch-send 请求==,body:{}", JSON.toJSONString(body));
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(body, headers);

                RestTemplate restTemplate = new RestTemplate();
                ResponseEntity<String> responseEntity = restTemplate.postForEntity(channel.getDomain(), request, String.class);

                String body1 = responseEntity.getBody();
                Any deserialize = JsonIterator.deserialize(body1);
                String code = deserialize.get("code").toString();
                if (!"0".equals(code)) {
                    LOGGER.error("== 发送短信 nx 失败 ==,res:{}", body1);
                }
            }
        });

        return new SendSmsRes("0", "submit-success");
    }


    private SendSmsRes sendByPasso(SmsSendChannelEntity channel, String mobile, String content, String sender) {

        pool.submit(new Runnable() {
            @Override
            public void run() {

                Map headers = Maps.newHashMap();
                headers.put("Content-Type", "application/x-www-form-urlencoded");
                Map<String, String> params = Maps.newHashMap();
                params.put("key", channel.getAccessKey());
                params.put("secret", channel.getAccessSecret());
                params.put("to", "91" + mobile);
                params.put("from", sender);
                params.put("text", content);

                String result = HttpUtil.postPage("http://api.paasoo.cn/json", params, headers);
                LOGGER.info("== 请求passo结果 ==,res:{}", result);
//                    Any deserialize = JsonIterator.deserialize(result);
//                    String code = deserialize.get("status").toString();
//                    String msg = deserialize.get("status_code").toString() + " # " + deserialize.get("batchid").toString();

            }
        });
        return new SendSmsRes("0", "submit-success");

    }

    public static void main(String[] args) {
        List<String> mobiles = new ArrayList<>();
        mobiles.add("8050843289");
        StringBuilder allMobile = new StringBuilder();
        for (String m : mobiles) {
            allMobile.append("91").append(m).append(",");
        }

        Map headers = Maps.newHashMap();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        Map<String, String> params = Maps.newHashMap();
        params.put("key", "4ygxyikn");
        params.put("secret", "4gMGPr1Y");
        params.put("to", allMobile.toString());
        params.put("from", "609934");
        params.put("text", "[RupeeMama] Get amazing new loans upto 85000 Rs. in less than 8 min! Hurry up before the offer ends! https://bit.ly/3DpLV6l Vasuki Information");

        String result = HttpUtil.postPage("https://api.paasoo.com/json", params, headers);
        LOGGER.info("== 访问支付链接接口 ==,res:{}", result);

        Any deserialize = JsonIterator.deserialize(result);
        String code = deserialize.get("status").toString();
        String msg = deserialize.get("status_code").toString() + " # " + deserialize.get("batchid").toString();

        System.err.println(result);
    }

}
